﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using ServiceStack.Redis;
using ServiceStack.Redis.Generic;
using ServiceStack.Text;

namespace DataAccessObject.Cache
{
    /// <summary>
    ///  Redis缓存
    ///  https://github.com/ServiceStack/
    ///  https://github.com/ServiceStack/ServiceStack.Redis
    ///  https://github.com/MSOpenTech/redis Windows 客户端
    /// </summary>
    public static class RedisCache
    {
        private static readonly string ReadWriteHosts = "localhost";
        private static readonly string ReadOnlyHosts = "localhost";

        #region -- 连接信息 --
        private static PooledRedisClientManager mPooledRedisClientManager;

        static RedisCache()
        {
            IEnumerable<string> readWriteHosts = ReadWriteHosts.Split(',');
            IEnumerable<string> readOnlyHosts = ReadOnlyHosts.Split(',');
            RedisClientManagerConfig config = new RedisClientManagerConfig
            {
                MaxWritePoolSize = 5,       // 最大“写”连接池链接数
                MaxReadPoolSize = 5,        // 最大“读”连接池链接数 
                AutoStart = true
            };
            mPooledRedisClientManager = new PooledRedisClientManager(readWriteHosts, readOnlyHosts, config);
        }
        #endregion
       
        #region ADD
        public static T Add<T>(T value)
        {
            using (IRedisClient redisClient = mPooledRedisClientManager.GetClient())
            {
                IRedisTypedClient<T> typedClient = redisClient.As<T>();
                return typedClient.Store(value);
            }
        }
        public static void Add<T>(IEnumerable<T> entities)
        {
            using (IRedisClient redisClient = mPooledRedisClientManager.GetClient())
            {
                redisClient.StoreAll<T>(entities);
            }
        }
        public static bool Add<T>(string key, T value)
        {
            using (IRedisClient redisClient = mPooledRedisClientManager.GetClient())
            {
                return redisClient.Add<T>(key, value);
            }
        }
        public static bool Add<T>(string key, T value, DateTime expiresAt)
        {
            using (IRedisClient redisClient = mPooledRedisClientManager.GetClient())
            {
                return redisClient.Add<T>(key, value, expiresAt);
            }
        }
        public static bool Add<T>(string key, T value, TimeSpan expiresIn)
        {
            using (IRedisClient redisClient = mPooledRedisClientManager.GetClient())
            {
                return redisClient.Add<T>(key, value, expiresIn);
            }
        } 
        #endregion

        #region GET

        public static IList<T> GetAll<T>()
        {
            using (IRedisClient redisClient = mPooledRedisClientManager.GetClient())
            {
                IRedisTypedClient<T> typedClient = redisClient.As<T>();
                return typedClient.GetAll();
            }
        }
        public static T GetById<T>(object id)
        {
            using (IRedisClient redisClient = mPooledRedisClientManager.GetClient())
            {
                IRedisTypedClient<T> typedClient = redisClient.As<T>();
                return typedClient.GetById(id);
            }
        }
        public static IList<T> GetByIds<T>(IEnumerable<T> ids)
        {
            using (IRedisClient redisClient = mPooledRedisClientManager.GetClient())
            {
                IRedisTypedClient<T> typedClient = redisClient.As<T>();
                return typedClient.GetByIds(ids);
            }
        }
        public static T Get<T>(string key)
        {
            using (IRedisClient redisClient = mPooledRedisClientManager.GetClient())
            {
                return redisClient.Get<T>(key);
            }
        }
        public static IDictionary<string, T> GetAll<T>(IEnumerable<string> keys)
        {
            using (IRedisClient redisClient = mPooledRedisClientManager.GetClient())
            {
                return redisClient.GetAll<T>(keys);
            }
        } 
        #endregion

        #region DELETE
        public static void Delete<T>(T entity)
        {
            using (IRedisClient redisClient = mPooledRedisClientManager.GetClient())
            {
                IRedisTypedClient<T> typedClient = redisClient.As<T>();
                typedClient.Delete(entity);
            }
        }
        public static void DeleteAll<T>()
        {
            using (IRedisClient redisClient = mPooledRedisClientManager.GetClient())
            {
                IRedisTypedClient<T> typedClient = redisClient.As<T>();
                typedClient.DeleteAll();
            }
        }
        public static void DeleteById<T>(object id)
        {
            using (IRedisClient redisClient = mPooledRedisClientManager.GetClient())
            {
                IRedisTypedClient<T> typedClient = redisClient.As<T>();
                typedClient.DeleteById(id);
            }
        }
        public static void DeleteByIds<T>(IEnumerable<object> ids) {
            using (IRedisClient redisClient = mPooledRedisClientManager.GetClient())
            {
                IRedisTypedClient<T> typedClient = redisClient.As<T>();
                typedClient.DeleteByIds(ids);
            }
        }

        public static bool Delete(string key)
        {
            using (IRedisClient redisClient = mPooledRedisClientManager.GetClient())
            {
                return redisClient.Remove(key);
            }
        }
        public static void Delete(IEnumerable<string> keys)
        {
            using (IRedisClient redisClient = mPooledRedisClientManager.GetClient())
            {
                redisClient.RemoveAll(keys);
            }
        }
        #endregion

        #region UPDATE

        public static bool Replace<T>(string key, T value) {
            using (IRedisClient redisClient = mPooledRedisClientManager.GetClient())
            {
                return redisClient.Replace<T>(key, value);
            }
        }
        public static bool Replace<T>(string key, T value, DateTime expiresAt) {
            using (IRedisClient redisClient = mPooledRedisClientManager.GetClient())
            {
                return redisClient.Replace(key, value, expiresAt);
            }
        }
        public static bool Replace<T>(string key, T value, TimeSpan expiresIn)
        {
            using (IRedisClient redisClient = mPooledRedisClientManager.GetClient())
            {
                return redisClient.Replace(key, value, expiresIn);
            }
        }
        public static bool Set<T>(string key, T value)
        {
            using (IRedisClient redisClient = mPooledRedisClientManager.GetClient())
            {
                return redisClient.Set(key, value);
            }
        }
        public static bool Set<T>(string key, T value, DateTime expiresAt)
        {
            using (IRedisClient redisClient = mPooledRedisClientManager.GetClient())
            {
                return redisClient.Set(key, value, expiresAt);
            }
        }
        public static bool Set<T>(string key, T value, TimeSpan expiresIn)
        {
            using (IRedisClient redisClient = mPooledRedisClientManager.GetClient())
            {
                return redisClient.Set(key, value, expiresIn);
            }
        }
        public static void SetAll<T>(IDictionary<string, T> values)
        {
            using (IRedisClient redisClient = mPooledRedisClientManager.GetClient())
            {
                redisClient.SetAll<T>(values);
            }
        }
        #endregion

        #region PAGEING
        public static List<T> GetRangeFromList<T>(IRedisList<T> fromList, int startingFrom, int endingAt)
        {
            using (IRedisClient redisClient = mPooledRedisClientManager.GetClient())
            {
                IRedisTypedClient<T> typedClient = redisClient.As<T>();
                return typedClient.GetRangeFromList(fromList, startingFrom, endingAt);
            }
        }
        public static List<T> SortList<T>(IRedisList<T> fromList, int startingFrom, int endingAt)
        {
            using (IRedisClient redisClient = mPooledRedisClientManager.GetClient())
            {
                IRedisTypedClient<T> typedClient = redisClient.As<T>();
                return typedClient.SortList(fromList, startingFrom, endingAt);
            }
        }
        public static List<T> GetRangeFromSortedSet<T>(IRedisSortedSet<T> set, int fromRank, int toRank, bool asc = true)
        {
            using (IRedisClient redisClient = mPooledRedisClientManager.GetClient())
            {
                IRedisTypedClient<T> typedClient = redisClient.As<T>();
                if (asc)
                {
                    return typedClient.GetRangeFromSortedSet(set, fromRank, toRank);
                }
                else
                {
                    return typedClient.GetRangeFromSortedSetDesc(set, fromRank, toRank);
                }
            }
        }
        #endregion

        public static long Decrement(string key, uint amount) //-
        {
            using (IRedisClient redisClient = mPooledRedisClientManager.GetClient())
            {
                return redisClient.Decrement(key, amount);
            }
        }
        public static long Increment(string key, uint amount) //+
        {
            using (IRedisClient redisClient = mPooledRedisClientManager.GetClient())
            {
                return redisClient.Increment(key, amount);
            }
        }
        public static void FlushAll()
        {
            using (IRedisClient redisClient = mPooledRedisClientManager.GetClient())
            {
                redisClient.FlushAll();
            }
        }

    }
}